package com.wao.editor.service;

import com.wao.editor.domain.ActionMap;
import com.wao.editor.domain.AppInfo;
import com.wao.editor.domain.BaseState;
import com.wao.editor.domain.State;
import org.json.JSONException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Component
public class ActionEnter {

    private final ConfigManager configManager;

    private final FileManager fileManager;

    private HttpServletRequest request = null;

    private String actionType = null;

    public ActionEnter(ConfigManager configManager, FileManager fileManager) {
        this.configManager = configManager;
        this.fileManager = fileManager;
    }

    public String exec(HttpServletRequest request) {

        this.request = request;
        this.actionType = request.getParameter("action");
        String callbackName = this.request.getParameter("callback");

        if (callbackName != null) {

            if (!validCallbackName(callbackName)) {
                return new BaseState(false, AppInfo.ILLEGAL).toJSONString();
            }

            return callbackName + "(" + this.invoke() + ");";

        } else {
            return this.invoke();
        }

    }

    public String invoke() {

        if (actionType == null || !ActionMap.mapping.containsKey(actionType)) {
            return new BaseState(false, AppInfo.INVALID_ACTION).toJSONString();
        }

        if (this.configManager == null || !this.configManager.valid()) {
            return new BaseState(false, AppInfo.CONFIG_ERROR).toJSONString();
        }

        State state = null;

        int actionCode = ActionMap.getType(this.actionType);

        Map<String, Object> conf = null;
        try {
            switch (actionCode) {

                case ActionMap.CONFIG:
                    return configManager.getAllConfig().toString();

                case ActionMap.UPLOAD_IMAGE:
                case ActionMap.UPLOAD_SCRAWL:
                case ActionMap.UPLOAD_VIDEO:
                case ActionMap.UPLOAD_FILE:
                    conf = configManager.getConfig(actionCode);
                    state = fileManager.upload(request, conf);
                    break;

                case ActionMap.CATCH_IMAGE:
                    conf = configManager.getConfig(actionCode);
                    String[] list = this.request.getParameterValues((String) conf.get("fieldName"));
                    state = fileManager.capture(list, conf);
                    break;

                case ActionMap.LIST_IMAGE:
                case ActionMap.LIST_FILE:
                    conf = configManager.getConfig(actionCode);
                    int start = this.getStartIndex();
                    String marker = this.getMarker();
                    state = fileManager.listFile(start, marker, (Integer) conf.get("count"));
                    break;

            }
        } catch (JSONException e) {
            state = new BaseState(false, AppInfo.CONFIG_ERROR);
        }

        return state.toJSONString();

    }

    public int getStartIndex() {

        String start = this.request.getParameter("start");
        try {
            return Integer.parseInt(start);
        } catch (Exception e) {
            return 0;
        }

    }

    public String getMarker() {

        String marker = this.request.getParameter("marker");
        return marker;
    }

    /**
     * callback参数验证
     */
    public boolean validCallbackName(String name) {

        if (name.matches("^[a-zA-Z_]+[\\w0-9_]*$")) {
            return true;
        }

        return false;

    }

}
